-
使用Thread类开发多线程程序的步骤:
- 自定义一个子类,继承Thread
- 在子类中,重写run()方法(run方法中书写的是线程要执行的任务代码)
Thread类中包含了创建并执行多线程的功能方法+线程要执行的任务(耦合度过高) - 创建一个子类对象
- 通过子类对象调用.start() 开启一个新线程并执行
-
使用Runnable接口开发多线程的步骤:
- 自定义一个实现Runnable接口的子类
- 在子类重写run方法
- 创建一个子类对象,并把该对象作为参数传递给Thread对象
- 创建一个Thread对象,并把实现Runnable接口的子类对象作为参数
- 调用Thread对象中的start方法
-
使用Runnable接口比Thread类的优点:
- 适合多个程序实现共享同一份资源
- 实现了解耦
- 避免Java中的单继承
-
实现Callable接口来创建线程:
- 自定义一个子类实现Callable
- 在子类中重写call方法
- 创建线程池
- 创建Callable子类对象
- 把Callable对象作为参数传递给线程池
- 发生原因:
-
安全问题都是由全局变量及静态变量造成的
-
多个线程同时对一个共享数据进行访问(在访问的同时存在修改操作),由于CPU切换不同的线程可能存在: A线程进行了修改,B线程却使用了修改前的数据
-
解决方案:
- 本质:把多线程变成单线程
- 引入线程同步机制
- 同步代码块
- 针对run方法中的代码,使用synchronized关键字,把部分代码添加同步机制
- 同步机制:在同一个而时间,只能有一个线程执行
- 原理:线程在执行之前先获取到一个锁,然后开始执行线程任务,只有拿到锁的线程执行完包含在synchronized代码块中的内容之后,才会释放锁,才可以让其他线程拿到这个锁
- 同步机制,关键是实现利用:锁(对象锁)
- 锁: 对象锁。任何对象都可以当锁使用
- String lock = new String()
- Object lock = new Object()
- 锁: 对象锁。任何对象都可以当锁使用
- 同步机制:在同一个而时间,只能有一个线程执行
- 针对run方法中的代码,使用synchronized关键字,把部分代码添加同步机制
- 同步方法
- 针对方法进行同步,同步方法只能用在方法上
- 格式:public synchronized void method(){...}
- 同步方法中的锁:
- 非静态方法:锁是this(锁,当前对象)
- 静态方法:静态方法没有对象的概念。所示Class(锁,类名.class)
- 锁机制
- 同步代码块
-
从线程的创建开始,一直到线程的销毁,整个过程称为:生命周期
- 划分:
- 创建 start() 线程创建成功
- 就绪
- 运行
- 死亡
- 控制方法:
- sleep() 当前执行的线程进入睡眠状态
- join() 等待当前线程死亡,当前线程必须执行完才能执行其他线程
- setDeamon() 设置当前线程为和守护线程,特点:当没有普通线程在执行时,守护线程也停止运行